package com.wsoft.hr.pm.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wsoft.core.exception.Asserts;
import com.wsoft.core.service.CodeRuleService;
import com.wsoft.core.utils.LoginUserUtil;
import com.wsoft.hr.pm.constant.HrPmCodeConstant;
import com.wsoft.hr.pm.entity.HrPmCycleEntity;
import com.wsoft.hr.pm.enums.CycleTypeEnum;
import com.wsoft.hr.pm.mapper.HrPmCycleMapper;
import com.wsoft.hr.pm.query.cycle.CycleInsertQuery;
import com.wsoft.hr.pm.query.cycle.CycleListQuery;
import com.wsoft.hr.pm.query.cycle.CycleUpdateEnableQuery;
import com.wsoft.hr.pm.query.cycle.CycleUpdateQuery;
import com.wsoft.hr.pm.service.IHrPmCycleService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.Month;
import java.time.YearMonth;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 活动周期 服务实现类
 * </p>
 *
 * @author zhanggukai
 * @since 2025年02月25日 11:13:43
 */
@Service
public class HrPmCycleServiceImpl extends ServiceImpl<HrPmCycleMapper, HrPmCycleEntity> implements IHrPmCycleService {

    @Resource
    private CodeRuleService codeRuleService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insert(CycleInsertQuery query) {
        HrPmCycleEntity entity = Convert.convert(HrPmCycleEntity.class, query);
        Object code = codeRuleService.initCode(HrPmCodeConstant.HR_PM_CYCLE_CODE, null, 1);
        entity.setCode(String.valueOf(code));
        entity.setEnable(0);
        entity.setHrOrgId(LoginUserUtil.getUserInfo().getHrOrgId());
        boolean save = save(entity);
        if (save){
            if (query.getAutoCycle()){
                generateCycles(query);
            }
        }
        return save;
    }

    @Override
    public boolean update(CycleUpdateQuery query) {
        HrPmCycleEntity entity = Convert.convert(HrPmCycleEntity.class, query);
        HrPmCycleEntity cycle = getById(entity.getId());
        if (!cycle.getEnable().equals(0)){
            Asserts.fail("[hr.pm.target.status.error]");
        }
        return updateById(entity);
    }

    @Override
    public boolean delete(Long id) {
        HrPmCycleEntity cycle = getById(id);
        if (!cycle.getEnable().equals(0)){
            Asserts.fail("[hr.pm.target.status.error]");
        }
        return removeById(id);
    }

    @Override
    public HrPmCycleEntity get(Long id) {
        return getById(id);
    }

    @Override
    public PageInfo<HrPmCycleEntity> pageList(CycleListQuery query) {
        PageHelper.startPage(query.getPageNum(), query.getPageSize());
        QueryWrapper<HrPmCycleEntity> queryWrapper = new QueryWrapper<>();
        if (StrUtil.isNotBlank(query.getName())){
            queryWrapper.lambda().like(HrPmCycleEntity::getName,query.getName());
        }
        if (StrUtil.isNotBlank(query.getYears())){
            queryWrapper.lambda().eq(HrPmCycleEntity::getYears,query.getYears());
        }
        if (StrUtil.isNotBlank(query.getType())){
            queryWrapper.lambda().eq(HrPmCycleEntity::getType,query.getType());
        }
        if (StrUtil.isNotBlank(query.getBeginDate())){
            queryWrapper.lambda().ge(HrPmCycleEntity::getBeginDate,query.getBeginDate());
        }
        if (StrUtil.isNotBlank(query.getEndData())){
            queryWrapper.lambda().le(HrPmCycleEntity::getEndData,query.getEndData());
        }
        if (StrUtil.isNotBlank(query.getEndData())){
            queryWrapper.lambda().le(HrPmCycleEntity::getEndData,query.getEndData());
        }
        if (query.getEnable()!=null){
            queryWrapper.lambda().eq(HrPmCycleEntity::getEnable,query.getEnable());
        }

        return PageInfo.of(list(queryWrapper));
    }

    @Override
    public boolean enableCycle(CycleUpdateEnableQuery query) {
        HrPmCycleEntity entity = Convert.convert(HrPmCycleEntity.class, query);
        return updateById(entity);
    }

    @Override
    public void generateCycles(CycleInsertQuery query) {
        // 根据周期类型生成周期
       if (query.getType().equals(CycleTypeEnum.SEMI_ANNUAL.getType())){
           CycleInsertQuery insert = new CycleInsertQuery();
           insert.setName(query.getYears()+"下半年绩效考核");
           insert.setYears(query.getYears());
           insert.setBeginDate(query.getBeginDate().plusMonths(6));
           insert.setEndData(query.getEndData().plusMonths(6));
           insert.setAutoCycle(false);
           insert.setExpireDate(query.getExpireDate().plusMonths(6));
           insert(insert);
       }
       if (query.getType().equals(CycleTypeEnum.QUARTER.getType())){
           //生成剩余季度
           generateRemainingQuarters(query);
       }
       if(query.getType().equals(CycleTypeEnum.MONTH.getType())){
           //生成剩余月份
           generateRemainingMonths(query);
       }
    }

    @Override
    public boolean firstAddCycle(CycleInsertQuery query) {
        QueryWrapper<HrPmCycleEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(HrPmCycleEntity::getYears,query.getYears());
        if (count(queryWrapper)>0){
            return false;
        }
       return true;
    }


    @Override
    public String checkTimeOverlap(CycleUpdateQuery cycle) {
        List<HrPmCycleEntity> list = list();
        List<HrPmCycleEntity> collect = list.stream().filter(e -> !e.getId().equals(cycle.getId())&&e.getBeginDate().equals(cycle.getBeginDate()) && e.getEndData().equals(cycle.getEndData())&&!e.getName().equals(cycle.getName())).collect(Collectors.toList());
        if (!collect.isEmpty()) {
            return "完全重叠: 已存在[" + collect.stream().map(HrPmCycleEntity::getName).collect(Collectors.joining(",")) + "]";
        }
        List<HrPmCycleEntity> collect1 = list.stream().filter(e -> !e.getId().equals(cycle.getId())&&!e.getBeginDate().isAfter(cycle.getEndData()) && !cycle.getBeginDate().isBefore(e.getEndData())&&!e.getName().equals(cycle.getName())).collect(Collectors.toList());
        if (!collect1.isEmpty()) {
            return "部分重叠: 已存在[" + collect1.stream().map(HrPmCycleEntity::getName).collect(Collectors.joining(",")) + "]";
        }
        return null;
    }

    @Override
    public List<HrPmCycleEntity> getByIds(List<String> ids) {

        Set<String> idSet = new HashSet<>(ids);
        for (String id : ids) {
            if(id.contains(StrUtil.COMMA)){
                idSet.addAll( Arrays.asList(id.split(StrUtil.COMMA)));
            }else{
                idSet.add(id);
            }
        }
        return super.listByIds(idSet);
    }

    /**
     * 根据 startTime 判断所属季度，并生成本年度剩余季度
     *
     * @param query
     * @return 本年度剩余季度的起止时间列表
     */
    public void generateRemainingQuarters(CycleInsertQuery query) {
        // 获取 startTime 所属的季度
        int startQuarter = getQuarter(query.getBeginDate());
        int year = query.getBeginDate().getYear();

        // 生成从 startQuarter 到第 4 季度的所有季度
        for (int i = startQuarter+1; i <= 4; i++) {
            CycleInsertQuery quarterRange = getQuarterRange(year, i);
            quarterRange.setAutoCycle(false);
            quarterRange.setType(query.getType());
            quarterRange.setExpireDate(query.getExpireDate().plusMonths(i* 3L));
            insert(quarterRange);
        }
    }

    /**
     * 根据年份和季度编号获取季度的起止时间
     *
     * @param year  年份
     * @param quarter 季度编号（1-4）
     * @return 季度的起止时间
     */
    private CycleInsertQuery getQuarterRange(int year, int quarter) {
        CycleInsertQuery insert = new CycleInsertQuery();
        insert.setYears(String.valueOf(year));
        switch (quarter) {
            case 1:
                insert.setName(year+"第一季度");
                insert.setBeginDate(LocalDate.of(year, Month.JANUARY, 1));
                insert.setEndData(LocalDate.of(year, Month.MARCH, 31));
                break;
            case 2:
                insert.setName(year+"第二季度");
                insert.setBeginDate(LocalDate.of(year, Month.APRIL, 1));
                insert.setEndData(LocalDate.of(year, Month.JUNE, 30));
                break;
            case 3:
                insert.setName(year+"第三季度");
                insert.setBeginDate(LocalDate.of(year, Month.JULY, 1));
                insert.setEndData(LocalDate.of(year, Month.SEPTEMBER, 30));
                break;
            case 4:
                insert.setName(year+"第三季度");
                insert.setBeginDate(LocalDate.of(year, Month.OCTOBER, 1));
                insert.setEndData(LocalDate.of(year, Month.DECEMBER, 31));
                break;
            default:
                Asserts.fail("无效的季度编号: " + quarter);
        }
        return insert;
    }

    /**
     * 根据日期判断所属季度
     *
     * @param date 日期
     * @return 季度编号（1-4）
     */
    private int getQuarter(LocalDate date) {
        int month = date.getMonthValue();
        if (month <= 3) {
            return 1;
        } else if (month <= 6) {
            return 2;
        } else if (month <= 9) {
            return 3;
        } else if (month <= 12) {
            return 4;
        }
        throw new IllegalArgumentException("无效的月份: " + month);
    }

    /**
     * 根据当前月份生成剩余月份
     *
     * @param query 当前日期
     * @return 剩余月份的起止时间列表
     */
    private void generateRemainingMonths(CycleInsertQuery query) {

        // 获取当前年份和月份
        int year = query.getBeginDate().getYear();
        int currentMonth = query.getBeginDate().getMonthValue();

        // 生成从当前月份到 12 月的所有月份
        for (int i = currentMonth+1; i <= 12; i++) {
            CycleInsertQuery insert = getMonthRange(year, i);
            insert.setAutoCycle(false);
            insert.setType(query.getType());
            insert.setExpireDate(query.getExpireDate().plusMonths(i-1));
            insert(insert);
        }
    }
    /**
     * 根据年份和月份编号获取月份的起止时间
     *
     * @param year  年份
     * @param month 月份编号（1-12）
     * @return 月份的起止时间
     */
    private  CycleInsertQuery getMonthRange(int year, int month) {
        CycleInsertQuery insert = new CycleInsertQuery();
        YearMonth yearMonth = YearMonth.of(year, month);
        // 月份的第一天
        insert.setBeginDate(yearMonth.atDay(1));
        // 月份的最后一天
        insert.setEndData(yearMonth.atEndOfMonth());
        insert.setName(year+"-"+month+"月考核周期");
        insert.setYears(String.valueOf(year));
        return insert;
    }
}
